﻿using FreesenseSubAIS.Common;
using FreesenseSubAIS.Core;
using FreesenseSubAIS.InspProcess;
using NLog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FreesenseSubAIS.ImageProcess
{
    internal class ImageManage
    {
        private ILogger _imageLog;
        private List<ImageProcessGroup> _inspGroup;
        private List<GroupResult> _listGrR;
        private List<ICameraAdapter> _listVircamera;
        private bool[] _arrShotEvent;
        private AutoResetEvent[] _arrResultEvent;
        private static readonly ImageManage _instance = new ImageManage();
        public event EventHandler<ResultDisplayRowResult> RefreshGroupItem;
        public event EventHandler<GroupResult> RefreshGroupResult;
        public ConcurrentDictionary<string, int> PicDictionary;
        public Tuple<string, Bitmap> FifoImage;
        public static ImageManage Instance { get { return _instance; } }
        private ImageManage()
        {
            _imageLog = LogManager.GetCurrentClassLogger();
            PicDictionary = new ConcurrentDictionary<string, int>();
            Device.DeviceEntityControl.ImageReceiveed += ImageAnalysis;
            _inspGroup = new List<ImageProcessGroup>();
            _listVircamera = new List<ICameraAdapter>();
            foreach (var c in Device.DeviceEntityControl.Cameras)
            {
                var param = Device.Parameter.CameraList.Find(x => x.CameraName.Equals(c.CameraName));
                if (param != null)
                {
                    var group = new ImageProcessGroup(param);
                    group.DisGroupItemResult += Group_DisGroupItemResult; ;
                    group.OnBackPicCount += Group_OnBackPicCount;
                    group.OnBackOneShot += Group_OnBackOneShot;
                    group.OnBackGroupResult += Group_OnBackGroupResult;
                    _inspGroup.Add(group);
                    PicDictionary.TryAdd(param.CameraName, 0);
                    Device.DitUseVirtual.Add(param.CameraName, false);
                }
            }
            _arrShotEvent = new bool[_inspGroup.Count];
            _arrResultEvent = new AutoResetEvent[_inspGroup.Count];
            _listGrR = new List<GroupResult>();
        }

        private void Group_DisGroupItemResult(object sender, ResultDisplayRowResult e)
        {
            if (Device.DisDetail && RefreshGroupItem != null)
                RefreshGroupItem(sender, e);
        }

        private void Group_OnBackOneShot(object sender, Bitmap e)
        {
            if (FifoImage != null)
                FifoImage.Item2.Dispose();
            FifoImage = new Tuple<string, Bitmap>(sender as string, e);
        }

        private void Group_OnBackGroupResult(object sender, GroupResult e)
        {
            var index = Device.DeviceEntityControl.Cameras.FindIndex(x => x.CameraName.Equals(sender as string));
            RefreshGroupResult?.Invoke(sender, e);
            _listGrR.Add(e);
            _arrResultEvent[index].Set();
        }

        private void Group_OnBackPicCount(object sender, int e)
        {
            PicDictionary[sender as string] = e;
            var index = Device.DeviceEntityControl.Cameras.FindIndex(x => x.CameraName.Equals(sender as string));
            _arrShotEvent[index] = true;
        }

        /// <summary>
        /// 拦截不为检测的图像
        /// </summary>
        /// <param name="sender">图片源</param>
        /// <param name="e">图片</param>
        private void ImageAnalysis(object sender, Bitmap e)
        {
            string name = sender.ToString();
            _inspGroup.Find(x => x.Groupname.Equals(name)).ImageAnalysis(sender, e);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="cname"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public ResultDisplayRowResult QueryItem(string cname, int index)
        {
            try
            {
                var ind = _inspGroup.FindIndex(x => x.Groupname.Equals(cname));
                if (ind > -1)
                {
                    return _inspGroup[ind].Insprecord.ListResults.Find(x =>
                    (x as ResultDisplayRowResult).Index.Equals(index)) as ResultDisplayRowResult;
                }
            }
            catch
            { }
            return null;
        }
        public void RefreshInspItem()
        {
            foreach (var item in _inspGroup)
                item.RefreshDetial();
        }
        /// <summary>
        /// 等待拍完一组图
        /// </summary>
        /// <param name="time">超时时间</param>
        /// <returns>是否超时</returns>
        public bool WaitPicGroup(int time = -1)
        {
            var waitpics = new Judger(() => _arrShotEvent.All(x => x)) { Name = "等待相机拍图" };
            var cancell = CancellationToken.None;
            var timeout = waitpics.Sure(cancell, time);
            return timeout;
        }
        /// <summary>
        /// 设置曝光
        /// </summary>
        /// <param name="time">曝光数组</param>
        public void SetExposureTime(string[] cname, double[] time)
        {
            for (int i = 0; i < cname.Count(); i++)
            {
                var ind = Device.DeviceEntityControl.Cameras.FindIndex(x => x.CameraName.Equals(cname[i]));
                if (ind > -1)
                    Device.DeviceEntityControl.Cameras[ind].SetExprosetime(time[i]);
            }
        }
        /// <summary>
        /// 触发所有相机拍图
        /// </summary>
        public void OneShot(string[] cname)
        {
            if (Device.DeviceEntityControl.Cameras == null)
            {
                return;
            }
            for (int i = 0; i < cname.Count(); i++)
            {
                var ind = Device.DeviceEntityControl.Cameras.FindIndex(x => x.CameraName.Equals(cname[i]));
                if (ind < 0)
                    break;
                _arrShotEvent[i] = false;
                if (Device.DitUseVirtual[cname[i]])
                {
                    _listVircamera.Find(x => x.CameraName.Equals(cname[i])).AquireBitmap(InspEntity.InspState);
                }
                else
                {
                    Device.DeviceEntityControl.Cameras.Find(x => x.CameraName.Equals(cname[i])).OneShot();
                }
            }
        }
        public void SetCmd(string[] cname)
        {
            if (Device.DeviceEntityControl.Cameras == null)
            {
                return;
            }
            for (int i = 0; i < cname.Count(); i++)
            {
                var ind = _inspGroup.FindIndex(x => x.Groupname.Equals(cname[i]));
                if (ind < 0)
                    break;
                _inspGroup[ind].CmdInqueue(InspEntity.InspState);
            }
        }
        public void ContinueShot(string cname)
        {
            if (Device.DeviceEntityControl.Cameras != null)
            {
                Device.DeviceEntityControl.Cameras.Find(x => x.CameraName.Equals(cname)).ContinueShot();
            }
        }
        public void StopContinueShot(string cname)
        {
            if (Device.DeviceEntityControl.Cameras != null)
            {
                Device.DeviceEntityControl.Cameras.Find(x => x.CameraName.Equals(cname)).StopShot();
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="step">0为自动清灰并处理结果，1为手动查询</param>
        internal void Refrush(int step)
        {
            #region 记录ID、作业员、线体名、站台号
            #endregion 记录ID、作业员、线体名、站台号

            #region 相机采图数量、清灰图列表清空
            _listGrR.Clear();
            PicDictionary.Clear();
            foreach (var group in _inspGroup)
                PicDictionary.TryAdd(group.Groupname, 0);

            for (int i = 0; i < _arrShotEvent.Count(); i++)
            {
                _arrShotEvent[i] = false;
            }
            for (int i = 0; i < _arrResultEvent.Count(); i++)
            {
                if (_arrResultEvent[i] == null)
                    _arrResultEvent[i] = new AutoResetEvent(false);
                else
                    _arrResultEvent[i].Reset();
            }
            #endregion 相机采图数量、清灰图列表清空
            Device.UniqueID = DateTime.Now.ToString("HHmmss");
            foreach (var insp in _inspGroup)
                insp.Refrush(step);
            if (step != 0)
                return;
        }

        //public void ReceiveCmd(int[] temp, int picindex)
        //{
        //    _imageLog.Trace(string.Format("相机执行拍图:曝光{0},图号{1}", temp, picindex));
        //    try
        //    {
        //        #region  以前做法
        //        SetExposureTime(temp);
        //        InspEntity.InspState = picindex;
        //        if (picindex > -5 && picindex < 100)
        //        {
        //            _inspGroup.ForEach(x => x.CmdInqueue(picindex));
        //            OneShot();
        //            return;
        //        }
        //        #endregion
        //        return;
        //    }
        //    catch (Exception ex)
        //    {
        //        _imageLog.Error(string.Format("ReceiveCmd:异常信息{0}", ex.Message));
        //        return;
        //    }
        //}
        public bool WaitAllTask(int time)
        {
            var arrTask = _inspGroup.Select(x => x.WaitFinished(time));
            return arrTask.Any(x => x);
        }
        public bool GetTotalResult()
        {
            var res = WaitHandle.WaitAll(_arrResultEvent);
            return _listGrR.All(x => x.Result);
        }

        internal void ChangeVirtualCamera(string selectName, string path)
        {
            var ind = _listVircamera.FindIndex(x => x.CameraName.Equals(selectName));
            if (ind > -1)
            {
                _listVircamera.RemoveAt(ind);
            }
            ICameraAdapter virCamera = new CameraVirtual(selectName, path);
            virCamera.Init();
            virCamera.ImageReady += ImageAnalysis;
            _listVircamera.Add(virCamera);
            if (Device.DitUseVirtual.ContainsKey(selectName))
                Device.DitUseVirtual[selectName] = true;
        }
        internal void CancelVirtualCamera(string selectName)
        {
            var ind = _listVircamera.FindIndex(x => x.CameraName.Equals(selectName));
            if (ind > -1)
            {
                _listVircamera.RemoveAt(ind);
            }
            if (Device.DitUseVirtual.ContainsKey(selectName))
                Device.DitUseVirtual[selectName] = false;
        }

        //internal void ChangeVirtualCamera(string foldername)
        //{
        //    virCamera = new CameraVirtual(foldername);
        //    virCamera.Init();
        //    virCamera.ImageReady += ImageProcess;
        //    Device.UseVirtual = true;
        //}
        //internal void VirtualCameraDisable()
        //{
        //    Device.UseVirtual = false;
        //    if (virCamera != null)
        //    {
        //        virCamera.ImageReady -= ImageProcess;
        //        virCamera.Close();
        //    }
        //}

    }
}